bitkeeper revision 1.825.6.1 (406841d1slBO3r43lCv4miJBBlOJnA)
authorach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>
Mon, 29 Mar 2004 15:33:37 +0000 (15:33 +0000)
committerach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>
Mon, 29 Mar 2004 15:33:37 +0000 (15:33 +0000)
re-work pdb context

xen/arch/i386/pdb-stub.c
xen/arch/i386/traps.c
xen/common/debug-linux.c
xen/include/asm-i386/pdb.h

index 742eb85f8d73097483cf90f4cc09928fa7dd6b79..a4d64a6f6038da87605f9bccb7a380a16ae6eb61 100644 (file)
@@ -1,10 +1,13 @@
 
 /*
  * pervasive debugger
+ * www.cl.cam.ac.uk/netos/pdb
  *
  * alex ho
  * 2004
  * university of cambridge computer laboratory
+ *
+ * code adapted originally from kgdb & nemesis
  */
 
 #include <xen/lib.h>
@@ -32,9 +35,7 @@
 
 #define BUFMAX 400
 
-#define PDB_ID_OFFSET 2        /* all threads & domains are positive numbers */
-
-static const char hexchars[]="0123456789abcdef";
+static const char hexchars[] = "0123456789abcdef";
 
 static int remote_debug;
 
@@ -46,22 +47,29 @@ static int  pdb_in_buffer_ptr;
 static unsigned char  pdb_in_checksum;
 static unsigned char  pdb_xmit_checksum;
 
-struct pdb_ctx_element
+/* function pointers in the near future... */
+unsigned long pdb_linux_pid_ptbr (unsigned long cr3, int pid);
+void pdb_linux_get_values(char *buffer, int length, unsigned long address,
+                         int pid, unsigned long cr3);
+
+struct pdb_context
 {
-    int ctrl;
-    int info;
-    unsigned long ctrl_cr3;
-    unsigned long info_cr3;
+    int valid;
+    int domain;
+    int process;
+    unsigned long ptbr;                   /* cached page table base register */
 };
+struct pdb_context pdb_ctx;
 
-#define pdb_ctx_count 3
-enum pdb_levels {PDB_LVL_XEN = 0, PDB_LVL_GUESTOS, PDB_LVL_PROCESS};
-struct pdb_ctx_element pdb_ctx[pdb_ctx_count];
-int pdb_level = PDB_LVL_XEN;
+int pdb_continue_thread = 0;
+int pdb_general_thread = 0;
 
 void pdb_put_packet (unsigned char *buffer, int ack);
 
 int pdb_initialized = 0;
+int pdb_page_fault_possible = 0;
+int pdb_page_fault_scratch = 0;                     /* just a handy variable */
+int pdb_page_fault = 0;
 static int pdb_serhnd = -1;
 static int pdb_stepping = 0;
 
@@ -75,16 +83,6 @@ static inline unsigned char pdb_get_char(void)
     return serial_getc(pdb_serhnd);
 }
 
-static volatile int mem_err = 0;
-void set_mem_err (void)                                   /* NOT USED YET... */
-{
-    mem_err = 1;
-}
-
-/* These are separate functions so that they are so short and sweet
-   that the compiler won't save any registers (if there is a fault
-   to mem_fault, they won't get restored, so there better not be any
-   saved).  */
 int
 get_char (char *addr)
 {
@@ -106,38 +104,17 @@ pdb_process_query (char *ptr)
     }
     else if (strcmp(ptr, "fThreadInfo") == 0)
     {
+#ifdef PDB_PAST
         struct task_struct *p;
         u_long flags;
-       int buf_idx = 0;
-
-       {                                                /* case pdb_lvl_xen */
-           int count = 0;
-
-           read_lock_irqsave (&tasklist_lock, flags);
-
-           pdb_out_buffer[buf_idx++] = 'm';
-           for_each_domain ( p )
-           {
-               domid_t domain = p->domain + PDB_ID_OFFSET;
+#endif /* PDB_PAST */
 
-               if (count > 0)
-               {
-                   pdb_out_buffer[buf_idx++] = ',';
-               }
-               if (domain > 15)
-               {
-                   pdb_out_buffer[buf_idx++] = hexchars[domain >> 4];
-               }
-               pdb_out_buffer[buf_idx++] = hexchars[domain % 16];
-               count++;
-           }
-           pdb_out_buffer[buf_idx++] = 0;
-
-           read_unlock_irqrestore(&tasklist_lock, flags);
-       }
+        int buf_idx = 0;
 
-#ifdef PDB_FUTURE
+       pdb_out_buffer[buf_idx++] = 'l';
+       pdb_out_buffer[buf_idx++] = 0;
 
+#ifdef PDB_PAST
        switch (pdb_level)
        {
        case PDB_LVL_XEN:                        /* return a list of domains */
@@ -172,7 +149,7 @@ pdb_process_query (char *ptr)
            int foobar[20];
            int loop, total;
 
-           /* *** BUG: this cr3 is wrong wrong wrong */
+                                                       /* this cr3 is wrong! */
            total = pdb_linux_process_list(pdb_ctx[pdb_level].info_cr3,
                                           foobar, 20);
 
@@ -201,8 +178,7 @@ pdb_process_query (char *ptr)
        default:
            break;
        }
-
-#endif /* PDB_FUTURE */
+#endif /* PDB_PAST */
 
     }
     else if (strcmp(ptr, "sThreadInfo") == 0)
@@ -214,6 +190,16 @@ pdb_process_query (char *ptr)
     }
     else if (strncmp(ptr, "ThreadExtraInfo,", 16) == 0)
     {
+        int thread = 0;
+       char *message = "foobar ?";
+
+       ptr += 16;
+        if (hexToInt (&ptr, &thread))
+       {
+            mem2hex (message, pdb_out_buffer, strlen(message) + 1);
+       }
+
+#ifdef PDB_PAST
         int thread = 0;
        char message[16];
        struct task_struct *p;
@@ -227,6 +213,7 @@ pdb_process_query (char *ptr)
        {
             mem2hex ((char *)message, pdb_out_buffer, strlen(message) + 1);
        }
+#endif /* PDB_PAST */
 
 #ifdef PDB_FUTURE
       {
@@ -249,7 +236,7 @@ pdb_process_query (char *ptr)
     }
     else
     {
-        printk("pdb_process_query: unknown query [%s]\n", ptr);
+        printk("pdb: error, unknown query [%s]\n", ptr);
     }
 }
 
@@ -341,36 +328,48 @@ pdb_process_command (char *ptr, struct pt_regs *regs, unsigned long cr3,
 
     pdb_out_buffer[0] = 0;
 
-    if (pdb_ctx[pdb_level].ctrl_cr3 == 0 &&
-       pdb_ctx[pdb_level].ctrl >= 0)
+    if (pdb_ctx.valid == 1)
     {
-        struct task_struct *p;
+        if (pdb_ctx.domain == -1)                        /* pdb context: xen */
+       {
+           struct task_struct *p;
 
-       p = find_domain_by_id(pdb_ctx[pdb_level].ctrl);
-       if (p->mm.shadow_mode)
-         pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.shadow_table);
-       else
-         pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.pagetable);
-       put_task_struct(p);
+           p = &idle0_task;
+           if (p->mm.shadow_mode)
+               pdb_ctx.ptbr = pagetable_val(p->mm.shadow_table);
+           else
+               pdb_ctx.ptbr = pagetable_val(p->mm.pagetable);
+       }
+       else if (pdb_ctx.process == -1)             /* pdb context: guest os */
+       {
+           struct task_struct *p;
 
-       TRC(printk ("PROCESS: PDB SET CONTROL DOMAIN TO 0x%lx 0x%x\n",
-               pdb_ctx[pdb_level].ctrl_cr3, 
-               pdb_ctx[pdb_level].ctrl));
-    }
-    if (pdb_ctx[pdb_level].info_cr3 == 0 &&
-       pdb_ctx[pdb_level].info >= 0)
-    {
-        struct task_struct *p;
+           p = find_domain_by_id(pdb_ctx.domain);
+           if (p->mm.shadow_mode)
+               pdb_ctx.ptbr = pagetable_val(p->mm.shadow_table);
+           else
+               pdb_ctx.ptbr = pagetable_val(p->mm.pagetable);
+           put_task_struct(p);
+       }
+       else                                         /* pdb context: process */
+       {
+           struct task_struct *p;
+           unsigned long domain_ptbr;
 
-       p = find_domain_by_id(pdb_ctx[pdb_level].info);
-       if (p->mm.shadow_mode)
-         pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.shadow_table);
-       else
-         pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.pagetable);
-       put_task_struct(p);
-       TRC(printk ("PROCESS: PDB SET INFO DOMAIN TO 0x%lx 0x%x\n",
-               pdb_ctx[pdb_level].info_cr3, 
-               pdb_ctx[pdb_level].info));
+           p = find_domain_by_id(pdb_ctx.domain);
+           if (p->mm.shadow_mode)
+               domain_ptbr = pagetable_val(p->mm.shadow_table);
+           else
+               domain_ptbr = pagetable_val(p->mm.pagetable);
+           put_task_struct(p);
+
+           pdb_ctx.ptbr = domain_ptbr;
+           /* pdb_ctx.ptbr = pdb_linux_pid_ptbr(domain_ptbr, pdb_ctx.process); */
+       }
+
+       pdb_ctx.valid = 0;
+       TRC(printk ("pdb change context (dom:%d, proc:%d) now 0x%lx\n",
+                   pdb_ctx.domain, pdb_ctx.process, pdb_ctx.ptbr));
     }
 
     switch (*ptr++)
@@ -458,48 +457,20 @@ pdb_process_command (char *ptr, struct pt_regs *regs, unsigned long cr3,
 
         if (hexToInt (&next, &thread))
         {
-            if (thread > 0)
-            {
-                thread = thread - PDB_ID_OFFSET;
-            }
             if (*ptr == 'c')
             {
-               pdb_ctx[pdb_level].ctrl = thread;
-
-               if (thread > 0)
-               {
-                   struct task_struct *p = find_domain_by_id(thread);
-                   if (p->mm.shadow_mode)
-                     pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.shadow_table);
-                   else
-                     pdb_ctx[pdb_level].ctrl_cr3 = pagetable_val(p->mm.pagetable);
-                   put_task_struct(p);
-                   TRC(printk ("PDB SET CONTROL DOMAIN TO 0x%lx 0x%x\n",
-                           pdb_ctx[pdb_level].ctrl_cr3,
-                           pdb_ctx[pdb_level].ctrl));
-               }
+               pdb_continue_thread = thread;
             }
             else if (*ptr == 'g')
             {
-               pdb_ctx[pdb_level].info = thread;
-
-               if (thread > 0)
-               {
-                   struct task_struct *p = find_domain_by_id(thread);
-                   if (p->mm.shadow_mode)
-                     pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.shadow_table);
-                   else
-                     pdb_ctx[pdb_level].info_cr3 = pagetable_val(p->mm.pagetable);
-                   put_task_struct(p);
-                   TRC(printk ("PDB SET INFO DOMAIN TO 0x%lx 0x%x\n",
-                           pdb_ctx[pdb_level].info_cr3,
-                           pdb_ctx[pdb_level].info));
-               }
+               pdb_general_thread = thread;
             }
             else
             {
-                printk ("ack, unknown command %c (thread: %d)\n", 
+                printk ("pdb error: unknown set thread command %c (%d)\n", 
                         *ptr, thread);
+               strcpy (pdb_out_buffer, "E00");
+               break;
             }
         }
         strcpy (pdb_out_buffer, "OK");
@@ -528,20 +499,31 @@ pdb_process_command (char *ptr, struct pt_regs *regs, unsigned long cr3,
                 if (hexToInt (&ptr, &length))
                 {
                     ptr = 0;
-                    mem_err = 0;
 
-                    if (pdb_ctx[pdb_level].info >= 0)
+                   pdb_page_fault_possible = 1;
+                   pdb_page_fault = 0;
+                   if (addr >= PAGE_OFFSET)
+                   {
+                        mem2hex ((char *) addr, pdb_out_buffer, length); 
+                   }
+                   else if (pdb_ctx.process != -1)
+                   {
+                       pdb_linux_get_values(pdb_buffer, length, addr, 
+                                            pdb_ctx.process, pdb_ctx.ptbr);
+                        mem2hex (pdb_buffer, pdb_out_buffer, length); 
+                   }
+                    else
                     {
-                       pdb_get_values(pdb_buffer, length,
-                                      pdb_ctx[pdb_level].info_cr3, addr);
+                       pdb_get_values (pdb_buffer, length, 
+                                       pdb_ctx.ptbr, addr);
                         mem2hex (pdb_buffer, pdb_out_buffer, length);
                     }
-                    else
-                        mem2hex ((char *) addr, pdb_out_buffer, length); 
-                    if (mem_err)
-                    {
+
+                   pdb_page_fault_possible = 0;
+                   if (pdb_page_fault)
+                   {
                         strcpy (pdb_out_buffer, "E03");
-                    }
+                   }
                 }
            
         if (ptr)
@@ -560,13 +542,20 @@ pdb_process_command (char *ptr, struct pt_regs *regs, unsigned long cr3,
                 if (hexToInt (&ptr, &length))
                     if (*(ptr++) == ':')
                     {
-                        mem_err = 0;
-
-                        /* pdb_set_values(ptr, length, cr3, addr); */
-                        pdb_set_values(ptr, length, 
-                                      pdb_ctx[pdb_level].info_cr3, addr);
 
-                        if (mem_err)
+                       pdb_page_fault_possible = 1;
+                       pdb_page_fault = 0;
+                       if (addr >= PAGE_OFFSET)
+                       {
+                           hex2mem (ptr, (char *)addr, length);
+                       }
+                       else
+                       {
+                           pdb_set_values (ptr, length,
+                                           pdb_ctx.ptbr, addr);
+                       }
+                       pdb_page_fault_possible = 0;
+                        if (pdb_page_fault)
                         {
                             strcpy (pdb_out_buffer, "E03");
                         }
@@ -589,17 +578,9 @@ pdb_process_command (char *ptr, struct pt_regs *regs, unsigned long cr3,
 
         if (hexToInt (&ptr, &id))
         {
-               {                                        /* case pdb_lvl_xen */
-                   struct task_struct *p;
-                   id -= PDB_ID_OFFSET;
-                   if ( (p = find_domain_by_id(id)) == NULL)
-                       strcpy (pdb_out_buffer, "E00");
-                   else
-                       strcpy (pdb_out_buffer, "OK");
-                   put_task_struct(p);
-               }
+           strcpy (pdb_out_buffer, "E00");
 
-#ifdef PDB_FUTURE
+#ifdef PDB_PAST
 
            switch (pdb_level)                             /* previous level */
            {
@@ -647,7 +628,7 @@ pdb_process_command (char *ptr, struct pt_regs *regs, unsigned long cr3,
                }
            }
 
-#endif /* PDB_FUTURE */
+#endif /* PDB_PAST */
         }
         break;
     }
@@ -981,14 +962,21 @@ int pdb_change_values_one_page(u_char *buffer, int length,
     l2_table += l2_table_offset(addr);
     if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 
     {
-        struct task_struct *p = find_domain_by_id(0);
-       printk ("pdb error: cr3: 0x%lx    dom0cr3:  0x%lx\n",  cr3,
-               p->mm.shadow_mode ? pagetable_val(p->mm.shadow_table)
-                                 : pagetable_val(p->mm.pagetable));
-       put_task_struct(p);
-
-       printk ("pdb error: L2:0x%p (0x%lx) \n", 
-               l2_table, l2_pgentry_val(*l2_table));
+       if (pdb_page_fault_possible == 1)
+       {
+           pdb_page_fault = 1;
+           TRC(printk("pdb: L2 error (0x%lx)\n", addr));
+       }
+       else
+       {
+           struct task_struct *p = find_domain_by_id(0);
+           printk ("pdb error: cr3: 0x%lx    dom0cr3:  0x%lx\n",  cr3,
+                   p->mm.shadow_mode ? pagetable_val(p->mm.shadow_table)
+                   : pagetable_val(p->mm.pagetable));
+           put_task_struct(p);
+           printk ("pdb error: L2:0x%p (0x%lx)\n", 
+                   l2_table, l2_pgentry_val(*l2_table));
+       }
        goto exit2;
     }
 
@@ -1012,9 +1000,17 @@ int pdb_change_values_one_page(u_char *buffer, int length,
        l1_table += l1_table_offset(addr); 
        if (!(l1_pgentry_val(*l1_table) & _PAGE_PRESENT))
        {
-           printk ("L2:0x%p (0x%lx) L1:0x%p (0x%lx)\n", 
-                   l2_table, l2_pgentry_val(*l2_table),
-                   l1_table, l1_pgentry_val(*l1_table));
+           if (pdb_page_fault_possible == 1)
+           {
+               pdb_page_fault = 1;
+               TRC(printk ("pdb: L1 error (0x%lx)\n", addr));
+           }
+           else
+           {
+               printk ("L2:0x%p (0x%lx) L1:0x%p (0x%lx)\n", 
+                       l2_table, l2_pgentry_val(*l2_table),
+                       l1_table, l1_pgentry_val(*l1_table));
+           }
            goto exit1;
        }
 
@@ -1028,11 +1024,11 @@ int pdb_change_values_one_page(u_char *buffer, int length,
         memcpy (buffer, page, length);
        bytes = length;
        break;
-    case __PDB_SET_VAL:                                         /* write */
+    case __PDB_SET_VAL:                                             /* write */
         hex2mem (buffer, page, length);
        bytes = length;
        break;
-    default:                                                  /* unknown */
+    default:                                                      /* unknown */
         printk ("error: unknown RW flag: %d\n", rw);
        return 0;
     }
@@ -1178,9 +1174,6 @@ int pdb_handle_exception(int exceptionVector,
         xen_regs->eip--;
     }
 
-    watchdog_save = watchdog_on;
-    watchdog_on = 0;
-
     /* Generate a signal for GDB. */
     switch ( exceptionVector )
     {
@@ -1202,6 +1195,9 @@ int pdb_handle_exception(int exceptionVector,
     pdb_out_buffer[3] = 0;
     pdb_put_packet(pdb_out_buffer, 1);
 
+    watchdog_save = watchdog_on;
+    watchdog_on = 0;
+
     do {
         pdb_out_buffer[0] = 0;
        pdb_get_packet(pdb_in_buffer);
@@ -1222,7 +1218,6 @@ void pdb_key_pressed(u_char key, void *dev_id, struct pt_regs *regs)
 void initialize_pdb()
 {
     extern char opt_pdb[];
-    int loop;
 
     /* Certain state must be initialised even when PDB will not be used. */
     memset((void *) &breakpoints, 0, sizeof(breakpoints));
@@ -1238,15 +1233,13 @@ void initialize_pdb()
         return;
     }
 
-    for (loop = 0; loop < pdb_ctx_count; loop++)
-    {
-        pdb_ctx[loop].ctrl = -1;
-       pdb_ctx[loop].info = -1;
-        pdb_ctx[loop].ctrl_cr3 = 0;
-       pdb_ctx[loop].info_cr3 = 0;
-    }
+    pdb_ctx.valid = 1;
+    pdb_ctx.domain = -1;
+    pdb_ctx.process = -1;
+    pdb_ctx.ptbr = 0;
 
-    printk("Initialized pervasive debugger (PDB) on port %s\n", opt_pdb);
+    printk("pdb: pervasive debugger (%s)   www.cl.cam.ac.uk/netos/pdb\n", 
+          opt_pdb);
 
     /* Acknowledge any spurious GDB packets. */
     pdb_put_char('+');
index 8ee67406d292eef9b62436539a8f5b524273b93c..7a012e147af5d20244db014a72dfd5413db2781e 100644 (file)
@@ -386,6 +386,15 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
 #endif
     }
 
+    if (pdb_page_fault_possible)
+    {
+        pdb_page_fault = 1;
+       /* make eax & edx valid to complete the instruction */
+       regs->eax = (long)&pdb_page_fault_scratch;
+       regs->edx = (long)&pdb_page_fault_scratch;
+       return;
+    }
+
     show_registers(regs);
     panic("CPU%d FATAL PAGE FAULT\n"
           "[error_code=%08x]\n"
index 34ba557cec8a1f166074acfd635d4cd71cceae8b..4fbcdf29180a197fe1415c3e6aeadac614fdace4 100644 (file)
@@ -1,13 +1,21 @@
+
+/*
+ * pervasive debugger
+ * www.cl.cam.ac.uk/netos/pdb
+ *
+ * alex ho
+ * 2004
+ * university of cambridge computer laboratory
+ *
+ * linux specific pdb stuff 
+ */
+
 #include <xen/config.h>
 #include <xen/types.h>
 #include <xen/lib.h>
 #include <hypervisor-ifs/dom0_ops.h>
 #include <asm/pdb.h>
 
-/* 
- * linux specific pdb stuff 
- */
-
 /* from linux/sched.h */
 #define PIDHASH_SZ (4096 >> 2)
 #define pid_hashfn(x)  ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
 #define ENTRIES_PER_L1_PAGETABLE 1024
 #define L1_PAGE_BITS ( (ENTRIES_PER_L1_PAGETABLE - 1) << PAGE_SHIFT )
 
-
 void pdb_linux_process_details (unsigned long cr3, int pid, char *buffer);
 
-
 /* adapted from asm-xen/page.h */
 static inline unsigned long machine_to_phys(unsigned long cr3,
                                             unsigned long machine)
@@ -46,9 +52,8 @@ static inline unsigned long machine_to_phys(unsigned long cr3,
   return phys;
 }
 
-
-#define pidhash_addr         0xc01971e0UL
-#define init_task_union_addr 0xc0182000UL
+unsigned long pdb_pidhash_addr         = 0xc01971e0UL;
+unsigned long pdb_init_task_union_addr = 0xc0182000UL;
 
 #define task_struct_mm_offset        0x2c
 #define task_struct_next_task_offset 0x48
@@ -59,16 +64,18 @@ static inline unsigned long machine_to_phys(unsigned long cr3,
 
 #define mm_struct_pgd_offset         0x0c
 
-/* read a byte from a process */
-u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
+/*
+ * find the task structure of a process (pid)
+ * given the cr3 of the guest os.
+ */
+unsigned long pdb_linux_pid_task_struct (unsigned long cr3, int pid)
 {
-  u_char result = 0;
-  unsigned long task_struct_p, mm_p, pgd, task_struct_pid;
-  unsigned long l2tab, page;
+  unsigned long task_struct_p = (unsigned long) NULL;
+  unsigned long task_struct_pid;
 
   /* find the task_struct of the given process */
   pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
-                cr3, pidhash_addr + pid_hashfn(pid) * 4);
+                cr3, pdb_pidhash_addr + pid_hashfn(pid) * 4);
 
   /* find the correct task struct */
   while (task_struct_p != (unsigned long)NULL)
@@ -79,15 +86,32 @@ u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
     {
       break;
     }
-    
+
     pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
                   cr3, task_struct_p + task_struct_pidhash_next_offset);
   }
-  if (task_struct_p == (unsigned long)NULL)
+  if (task_struct_p == (unsigned long) NULL)
   {
     /* oops */
-    printk ("error: pdb couldn't find process 0x%x\n", pid);
-    return 0;
+    printk ("pdb error: couldn't find process 0x%x (0x%lx)\n", pid, cr3);
+  }
+
+  return task_struct_p;
+}
+
+/*
+ * find the ptbr of a process (pid)
+ * given the cr3 of the guest os.
+ */
+unsigned long pdb_linux_pid_ptbr (unsigned long cr3, int pid)
+{
+  unsigned long task_struct_p;
+  unsigned long mm_p, pgd;
+
+  task_struct_p = pdb_linux_pid_task_struct(cr3, pid);
+  if (task_struct_p == (unsigned long) NULL)
+  {
+    return (unsigned long) NULL;
   }
 
   /* get the mm_struct within the task_struct */
@@ -97,6 +121,27 @@ u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
   pdb_get_values((u_char *) &pgd, sizeof(pgd),
                 cr3, mm_p + mm_struct_pgd_offset);
 
+  return pgd;
+}
+
+
+
+/* read a byte from a process 
+ *
+ * in: pid: process id
+ *     cr3: ptbr for the process' domain
+ *     addr: address to read
+ */
+
+u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
+{
+  u_char result = 0;
+  unsigned long pgd;
+  unsigned long l2tab, page;
+
+  /* get the process' pgd */
+  pgd = pdb_linux_pid_ptbr(cr3, pid);
+
   /* get the l2 table entry */
   pdb_get_values((u_char *) &l2tab, sizeof(l2tab),
                 cr3, pgd + (addr >> PGDIR_SHIFT) * 4);
@@ -114,8 +159,22 @@ u_char pdb_linux_get_value(int pid, unsigned long cr3, unsigned long addr)
   return result;
 }
 
-/* return 1 if is the virtual address is in the operating system's
-   address space, else 0 */
+void pdb_linux_get_values(char *buffer, int length, unsigned long address,
+                         int pid, unsigned long cr3)
+{
+    int loop;
+
+    /* yes, this can be optimized... a lot */
+    for (loop = 0; loop < length; loop++)
+    {
+        buffer[loop] = pdb_linux_get_value(pid, cr3, address + loop);
+    }
+}
+
+/*
+ * return 1 if is the virtual address is in the operating system's
+ * address space, else 0 
+ */
 int pdb_linux_address_space (unsigned long addr)
 {
     return (addr > PAGE_OFFSET);
@@ -135,9 +194,9 @@ int pdb_linux_process_list (unsigned long cr3, int array[], int max)
 
   /* task_p = init_task->next_task  */
   pdb_get_values((u_char *) &task_p, sizeof(task_p),
-                cr3, init_task_union_addr + task_struct_next_task_offset);
+                cr3, pdb_init_task_union_addr + task_struct_next_task_offset);
   
-  while (task_p != init_task_union_addr)
+  while (task_p != pdb_init_task_union_addr)
   {
       pdb_get_values((u_char *) &pid, sizeof(pid),
                     cr3, task_p + task_struct_pid_offset);
@@ -153,35 +212,14 @@ int pdb_linux_process_list (unsigned long cr3, int array[], int max)
   return count;
 }
 
-/* get additional details about a particular process:
+/*
+ * get additional details about a particular process
  */
 void pdb_linux_process_details (unsigned long cr3, int pid, char *buffer)
 {
-  unsigned long task_struct_p, task_struct_pid;
-
-  /* find the task_struct of the given process */
-  pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
-                cr3, pidhash_addr + pid_hashfn(pid) * 4);
+  unsigned long task_struct_p;
 
-  /* find the correct task struct */
-  while (task_struct_p != (unsigned long)NULL)
-  {
-    pdb_get_values((u_char *) &task_struct_pid, sizeof(task_struct_pid),
-                  cr3, task_struct_p + task_struct_pid_offset);
-    if (task_struct_pid == pid)
-    {
-      break;
-    }
-
-    pdb_get_values((u_char *) &task_struct_p, sizeof(task_struct_p),
-                  cr3, task_struct_p + task_struct_pidhash_next_offset);
-  }
-  if (task_struct_p == (unsigned long)NULL)
-  {
-    /* oops */
-    printk ("error: pdb couldn't find process 0x%x\n", pid);
-    return;
-  }
+  task_struct_p = pdb_linux_pid_task_struct(cr3, pid);
 
   pdb_get_values((u_char *) buffer, task_struct_comm_length,
                 cr3, task_struct_p + task_struct_comm_offset);
index 7bfe0254e3cb542b86097a99b334adaeacfa7e98..68efcbccafded74661d8f02777d5af1fd25d0fea 100644 (file)
@@ -1,6 +1,7 @@
 
 /*
  * pervasive debugger
+ * www.cl.cam.ac.uk/netos/pdb
  *
  * alex ho
  * 2004
@@ -18,6 +19,9 @@
 extern int pdb_initialized;
 extern int pdb_com_port;
 extern int pdb_high_bit;
+extern int pdb_page_fault_possible;
+extern int pdb_page_fault_scratch;
+extern int pdb_page_fault;
 
 extern void initialize_pdb(void);